package com.iursp.conf.interceptor;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import com.iursp.conf.annotation.CacheLock;

import java.lang.reflect.Method;

@Aspect
@Configuration
public class LockMethodInterceptor {
	@Autowired
	public LockMethodInterceptor(StringRedisTemplate lockRedisTemplate, CacheKeyGenerator cacheKeyGenerator) {
		this.lockRedisTemplate = lockRedisTemplate;
		this.cacheKeyGenerator = cacheKeyGenerator;
	}

	private final StringRedisTemplate lockRedisTemplate;
	private final CacheKeyGenerator cacheKeyGenerator;

	@Around("execution(public * *(..)) && @annotation(com.iursp.conf.annotation.CacheLock)")
	public Object interceptor(ProceedingJoinPoint pjp) {
		MethodSignature signature = (MethodSignature) pjp.getSignature();
		Method method = signature.getMethod();
		CacheLock lock = method.getAnnotation(CacheLock.class);
		if (StringUtils.isEmpty(lock.prefix())) {
			throw new RuntimeException("lock key don't null...");
		}
		final String lockKey = cacheKeyGenerator.getLockKey(pjp);
		try {
			final Boolean success = lockRedisTemplate.opsForValue().setIfAbsent(lockKey, "1");
			if (!success) {
				// TODO 应该抛出一个自定义的 CacheLockException 异常(暂未实现)
				throw new RuntimeException("请勿重复请求");
			}
			lockRedisTemplate.expire(lockKey, lock.expire(), lock.timeUnit());
			try {
				return pjp.proceed();
			} catch (Throwable throwable) {
				throw new RuntimeException("系统异常");
			}
		} finally {
			// lockRedisTemplate.delete(lockKey);
		}
	}
}
